package com.ruoyi.stock2.thread.aboutDownloadFailData;

import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.stock2.domain.DownTradedataFail;
import com.ruoyi.stock2.domain.TRADEDATA;
import com.ruoyi.stock2.mapper.TRADEDATAMapper;
import com.ruoyi.stock2.service.IDownTradedataFailService;
import com.ruoyi.stock2.utils.DateUtils2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

public class FailCompPingjun3 {
	private static final Logger log = LoggerFactory.getLogger(FailCompPingjun3.class);
	TRADEDATAMapper tradedataMapper;
	IDownTradedataFailService iDownTradedataFailService;
	// 单例实现
	public static FailCompPingjun3 getInstance() {
		return Singtonle.instance;
	}

	private static class Singtonle {
		private static FailCompPingjun3 instance = new FailCompPingjun3();
	}

	public void run() {
		tradedataMapper = (TRADEDATAMapper) SpringUtils.getBean(TRADEDATAMapper.class);
		iDownTradedataFailService = (IDownTradedataFailService) SpringUtils.getBean(IDownTradedataFailService.class);
		List<DownTradedataFail> stocks = iDownTradedataFailService.selectDownTradedataFailList(null);
		for (DownTradedataFail stock : stocks) {
			TRADEDATA tradeDataKey = new TRADEDATA(stock.getSymbol(),
					DateUtils2.formatStringToDate("2004-01-01", "yyyy-MM-dd"));
			List<TRADEDATA> list = tradedataMapper.get200ByKeyDateTimeDesc(tradeDataKey);
			completeVolumeAndaragPrice(list, DateUtils2.formatStringToDate(stock.getFromdate(), "yyyyMMdd"));
			list = null;
		}
	}

	/**
	 * @return 更新数据库的平均价格及平均交易量
	 * @param list
	 *            中包含为200天的记录 或 历史中所有的记录
	 */
	public void completeVolumeAndaragPrice(List<TRADEDATA> list, Date beginDateTime) {
		List<TRADEDATA> temp1 = new ArrayList<TRADEDATA>(30);
		ConcurrentLinkedQueue<TRADEDATA> concurrentLinkedQueue = new ConcurrentLinkedQueue<TRADEDATA>();
		for (int i = 0; i < list.size(); i++) {
			if (list.get(i).getDatetime().compareTo(beginDateTime) >= 0) {
				TRADEDATA tradeData = new TRADEDATA();
				BeanUtils.copyProperties(list.get(i), tradeData);
				tradeData.setDatetime(list.get(i).getDatetime());
				tradeData.setSymbol(list.get(i).getSymbol());
				tradeData.setZhang(ZhangFun(list, i));
				tradeData.setZhangfu(ZhangfuFun(list, i));
				if (list.size() - i >= 5)
					tradeData.setVolume5(pingJunFun(list, 5, i, "volume"));
				else
					tradeData.setVolume5(null);
				if (list.size() - i >= 10)
					tradeData.setVolume10(pingJunFun(list, 10, i, "volume"));
				else
					tradeData.setVolume10(null);
				if (list.size() - i >= 5)
					tradeData.setAverageprice5(pingJunFun(list, 5, i, "closePrice"));
				else
					tradeData.setAverageprice5(null);
				if (list.size() - i >= 10)
					tradeData.setAverageprice10(pingJunFun(list, 10, i, "closePrice"));
				else
					tradeData.setAverageprice10(null);
				if (list.size() - i >= 20)
					tradeData.setAverageprice20(pingJunFun(list, 20, i, "closePrice"));
				else {
					tradeData.setAverageprice20(null);
				}
				if (list.size() - i >= 60)
					tradeData.setAverageprice60(pingJunFun(list, 60, i, "closePrice"));
				else
					tradeData.setAverageprice60(null);

				//this.tradedataMapper.updateTRADEDATA(tradeData);
				concurrentLinkedQueue.offer(tradeData);
				
			} else {
				break;
			}
			
		}
		
		if(concurrentLinkedQueue.size()>0) {
        	
        	for(TRADEDATA obj:concurrentLinkedQueue) {
        		temp1.add(obj);
        		if( temp1.size() == 30 ) {
                	tradedataMapper.updateBatch(temp1);
                	temp1.clear();
                }
        	}
        	
        	if(temp1.size() > 0) {
            	tradedataMapper.updateBatch(temp1);
            	temp1.clear();
            }
        }
		
		concurrentLinkedQueue = null;
/*		if (list != null) {
			WeakReference<List<TRADEDATA>> gc1 = new WeakReference<List<TRADEDATA>>(list);
			int ii = 1;
			list = null;
			while (gc1.get() != null && ii != 3) {
				System.gc();
				ii++;
			}
		}*/
	}

	/*
	 * 通用计算平均值
	 */
	public BigDecimal pingJunFun(List<TRADEDATA> ls, int size, int num, String volumeOrClosePrice) {
		BigDecimal reback = new BigDecimal(0);
		for (int i = num; i < (num + size); i++) {
			if ("volume".equals(volumeOrClosePrice) && i < ls.size()) {
				reback = reback.add(new BigDecimal(ls.get(i).getVolume().toString()));
			} else if ("closePrice".equals(volumeOrClosePrice) && i < ls.size()) {
				reback = reback.add(new BigDecimal(ls.get(i).getCloseprice().toString()));
			}
		}
		return reback.divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP);
	}

	/*
	 * 通用计算差值
	 */
	public BigDecimal ZhangFun(List<TRADEDATA> ls, int num) {
		BigDecimal yesterDayPrice = new BigDecimal(0);
		BigDecimal todayPrice = new BigDecimal(0);
		if (num + 1 < ls.size()) {
			todayPrice = new BigDecimal(ls.get(num).getCloseprice().toString());
			yesterDayPrice = new BigDecimal(ls.get(num + 1).getCloseprice().toString());
		}
		return todayPrice.subtract(yesterDayPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
	}

	/*
	 * 通用计算涨幅
	 */
	public BigDecimal ZhangfuFun(List<TRADEDATA> ls, int num) {
		BigDecimal yesterDayPrice = new BigDecimal(0);
		BigDecimal todayPrice = new BigDecimal(0);
		BigDecimal result = new BigDecimal(0);
		if (num + 1 < ls.size()) {
			todayPrice = new BigDecimal(ls.get(num).getCloseprice().toString());
			yesterDayPrice = new BigDecimal(ls.get(num + 1).getCloseprice().toString());
			result = todayPrice.subtract(yesterDayPrice).divide(yesterDayPrice, 4, BigDecimal.ROUND_HALF_UP)
					.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
		}
		return result;
	}

}
